let user: object
user = { name: 'Henry' }
user = []
user = Object.prototype // 原型对象

// user = 'Henry' // 编译报错，改变了类型为字符串

// 注意，可以用大写的 Object类型，是指所有类型的原型指向
let user2: Object = {}
user2 = 'Henry'

console.log('===')

// 对象类型
let Bucky: { name: string; age: number } = {
  name: 'Bucky',
  age: 18
}
// 看个人习惯，我喜欢用这种方式（然后可能还会使用 type/interface 更方便的管理类型）
let Alice: {
  name: string
  age: number
} = {
  name: 'Alice',
  age: 20
}

// 推荐
type typeUser = {
  name: string
  age: number
}
let Bob: typeUser = {
  name: 'Bob',
  age: 20
}
// 推荐
interface IUser {
  name: string
  age: number
}
let King: IUser = {
  name: 'King',
  age: 18
}

console.log('===')

type typePerson = {
  id: number
  name: string
  age?: number
}

const henry: typePerson = {
  id: 101,
  name: 'Henry',
  age: 25
}
const Elisy: typePerson = {
  id: 102,
  name: 'Elisy'
}

console.log('===')

// 复杂对象类型
let complexA: {
  data: number[]
  myFunc: (item: number) => number[]
} = {
  data: [1, 2, 34],
  myFunc(num) {
    return [num]
  }
}
console.log(complexA)

// 如果类型一旦很多，就会显示很复杂，可以使用类型别名 type，或者是接口interface 将通用的提出来，都是可以的，也是推荐的做法
type myType = {
  data: number[]
  myFunc: (item: number) => number[]
}

let complexB: myType = {
  data: [1, 2, 34],
  myFunc(num) {
    return [num]
  }
}
console.log(complexB)

type typeComplex = {
  id?: number
  name: string
  hobbies: string[]
  gameMatrix: number[][] // 游戏开发中会用到的坐标处理
  sayHello: (message: string) => void
}
let complexC: typeComplex = {
  name: 'Henry',
  hobbies: ['coding', 'reading'],
  gameMatrix: [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
  ],
  sayHello(message) {
    console.log(`Hello, ${message}`)
  }
}

complexC.sayHello('早上好') //=> Hello, 早上好

export {}
